package com.xmall.pay.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeFastpayRefundQueryModel;
import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.internal.util.StringUtils;
import com.alipay.api.request.AlipayTradeFastpayRefundQueryRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.alipay.api.response.AlipayTradeFastpayRefundQueryResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.xmall.define.dict.PayTypeEnum;
import com.xmall.define.dict.PayPlatformEnum;
import com.xmall.define.base.ResultCode;
import com.xmall.define.dto.pay.AlipayRefundDto;
import com.xmall.define.dto.pay.AlipayRefundTradeDto;
import com.xmall.define.dto.pay.AlipayTradeDto;
import com.xmall.exception.XmallException;
import com.xmall.pay.config.AlipayConfigProperties;
import com.xmall.define.request.pay.OrderPaySuccessRequest;
import com.xmall.pay.service.IAlipayService;
import com.xmall.pay.service.IMsgService;
import com.xmall.define.request.pay.AlipayRefundRequest;
import com.xmall.define.request.pay.AlipayRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

@Slf4j
@Service
public class AlipayServiceImpl implements IAlipayService {

    @Resource
    private AlipayConfigProperties alipayConfigProperties;

    @Resource
    private IMsgService msgService;

    /**
     * 手机网站支付
     */
    @Override
    public String mobileWapPay(AlipayRequest request){
        try {
            // 商户订单号，商户网站订单系统中唯一订单号，必填
            String out_trade_no = new String(request.getOutTradeNo().getBytes("ISO-8859-1"),"UTF-8");
            // 订单名称，必填
            String subject = new String(request.getSubject().getBytes("ISO-8859-1"),"UTF-8");
            System.out.println(subject);
            // 付款金额，必填
            String total_amount=new String(request.getTotalAmount().getBytes("ISO-8859-1"),"UTF-8");
            // 商品描述，可空
            String body = new String(request.getBody().getBytes("ISO-8859-1"),"UTF-8");
            // 超时时间 可空
            String timeout_express = request.getTimeoutExpress();
            // 销售产品码 必填
            String product_code = "QUICK_WAP_WAY";
            // SDK 公共请求类，包含公共请求参数，以及封装了签名与验签，开发者无需关注签名与验签
            AlipayClient client = new DefaultAlipayClient(alipayConfigProperties.getUrl(), alipayConfigProperties.getAppid(), alipayConfigProperties.getRsaPrivateKey(), alipayConfigProperties.getFormat(), alipayConfigProperties.getCharset(), alipayConfigProperties.getAlipayPublicKey(), alipayConfigProperties.getSignType());
            AlipayTradeWapPayRequest alipay_request=new AlipayTradeWapPayRequest();

            // 封装请求支付信息
            AlipayTradeWapPayModel model=new AlipayTradeWapPayModel();
            model.setOutTradeNo(out_trade_no);
            model.setSubject(new String(subject.getBytes("ISO-8859-1"),"UTF-8"));
            model.setTotalAmount(total_amount);
            if(!StringUtils.isEmpty(body)) {
                model.setBody(new String(body.getBytes("ISO-8859-1"),"UTF-8"));
            }
            model.setTimeoutExpress(timeout_express);
            model.setProductCode(product_code);
            model.setPassbackParams(request.getOrderId().toString());
            alipay_request.setBizModel(model);
            // 设置异步通知地址
            alipay_request.setNotifyUrl(alipayConfigProperties.getNotifyUrl());
            // 设置同步地址
            alipay_request.setReturnUrl(request.getReturnUrl());

            // 调用SDK生成表单
            return client.pageExecute(alipay_request).getBody();
        } catch (Exception e) {
            e.printStackTrace();
            throw new XmallException(ResultCode.PAY_ALIPAY_MOBILE_WAP_ERROR);
        }
    }

    /**
     * 支付回调
     */
    @Override
    public String tradeNotify(HttpServletRequest request, HttpServletResponse out) {
        try {
            Map<String,String> params = new HashMap<>();
            Map requestParams = request.getParameterMap();
            for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
                String name = (String) iter.next();
                String[] values = (String[]) requestParams.get(name);
                String valueStr = "";
                for (int i = 0; i < values.length; i++) {
                    valueStr = (i == values.length - 1) ? valueStr + values[i]
                            : valueStr + values[i] + ",";
                }
                //乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
                //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
                params.put(name, valueStr);
            }
            log.info("alipay notify: {}", params);
            //商户订单号
            String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");

            //支付宝交易号
            String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8");

            //交易状态
            String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"),"UTF-8");

            // 自定义参数
            String passback_params = new String(request.getParameter("passback_params").getBytes("ISO-8859-1"),"UTF-8");

            //获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
            boolean verify_result = AlipaySignature.rsaCheckV1(params, alipayConfigProperties.getAlipayPublicKey(), alipayConfigProperties.getCharset(), alipayConfigProperties.getSignType());
            if(verify_result){
                if(trade_status.equals("TRADE_FINISHED")){

                } else if (trade_status.equals("TRADE_SUCCESS")){
                    OrderPaySuccessRequest paySuccessRequest = new OrderPaySuccessRequest();
                    paySuccessRequest.setOrderId(Long.valueOf(passback_params));
                    paySuccessRequest.setOrderSn(out_trade_no);
                    paySuccessRequest.setTradeNo(trade_no);
                    paySuccessRequest.setPayType(PayTypeEnum.ALI_PAY.getType());
                    paySuccessRequest.setPayPlatform(PayPlatformEnum.MOBILE_H5.getType());
                    paySuccessRequest.setPayTime(new Date());
                    msgService.sendPaySuccessMsg(paySuccessRequest);
                }
                return "success";
            }else{
                return "fail";
            }
        }catch (Exception e) {
            return "fail";
        }
    }

    /**
     * 交易查询
     */
    @Override
    public AlipayTradeDto tradeInfo(String orderSn, String aliTradeNo) {
        AlipayTradeDto tradeInfo = new AlipayTradeDto();
        // SDK 公共请求类，包含公共请求参数，以及封装了签名与验签，开发者无需关注签名与验签
        AlipayClient client = new DefaultAlipayClient(alipayConfigProperties.getUrl(), alipayConfigProperties.getAppid(), alipayConfigProperties.getRsaPrivateKey(), alipayConfigProperties.getFormat(), alipayConfigProperties.getCharset(), alipayConfigProperties.getAlipayPublicKey(), alipayConfigProperties.getSignType());
        AlipayTradeQueryRequest alipay_request = new AlipayTradeQueryRequest();

        AlipayTradeQueryModel model=new AlipayTradeQueryModel();
        model.setOutTradeNo(orderSn);
        if(StrUtil.isNotBlank(aliTradeNo)) {
            model.setTradeNo(aliTradeNo);
        }
        alipay_request.setBizModel(model);

        try {
            AlipayTradeQueryResponse response =client.execute(alipay_request);
            tradeInfo.setExists(true);
            tradeInfo.setTradeNo(response.getTradeNo());
            tradeInfo.setTradeStatus(response.getTradeStatus());
            log.info("order: {} trade status: {}", orderSn, response.getTradeStatus());
        }catch (Exception e) {
            log.info("order: {} trade not exist", orderSn);
            tradeInfo.setExists(false);
        }
        return tradeInfo;
    }

    /**
     * 退款查询
     */
    @Override
    public AlipayRefundTradeDto refundTradeInfo(String orderSn, String aliTradeNo, String refundNo) {
        AlipayRefundTradeDto tradeInfo = new AlipayRefundTradeDto();
        try {
            AlipayClient client = new DefaultAlipayClient(alipayConfigProperties.getUrl(), alipayConfigProperties.getAppid(), alipayConfigProperties.getRsaPrivateKey(), alipayConfigProperties.getFormat(), alipayConfigProperties.getCharset(), alipayConfigProperties.getAlipayPublicKey(), alipayConfigProperties.getSignType());
            AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();

            AlipayTradeFastpayRefundQueryModel model = new AlipayTradeFastpayRefundQueryModel();
            model.setOutTradeNo(orderSn);
            model.setTradeNo(aliTradeNo);
            model.setOutRequestNo(refundNo);
            request.setBizModel(model);

            AlipayTradeFastpayRefundQueryResponse response = client.execute(request);
            tradeInfo.setExists(true);
            tradeInfo.setRefundStatus(response.getRefundStatus());
            log.info("order: {} refund trade status: {}", orderSn, response.getRefundStatus());
        }catch (Exception e) {
            tradeInfo.setExists(false);
        }
        return tradeInfo;
    }

    /**
     * 退款
     */
    @Override
    public AlipayRefundDto refund(AlipayRefundRequest request) {
        AlipayRefundDto result = new AlipayRefundDto();
        try {
            AlipayClient client = new DefaultAlipayClient(alipayConfigProperties.getUrl(), alipayConfigProperties.getAppid(), alipayConfigProperties.getRsaPrivateKey(), alipayConfigProperties.getFormat(), alipayConfigProperties.getCharset(), alipayConfigProperties.getAlipayPublicKey(), alipayConfigProperties.getSignType());
            AlipayTradeRefundRequest alipay_request = new AlipayTradeRefundRequest();

            AlipayTradeRefundModel model=new AlipayTradeRefundModel();
            model.setOutTradeNo(request.getOutTradeNo());
            model.setTradeNo(request.getTradeNo());
            model.setRefundAmount(request.getRefundAmount());
            model.setRefundReason(new String(request.getRefundReason().getBytes("ISO-8859-1"),"UTF-8"));
            model.setOutRequestNo(request.getRefundNo());
            alipay_request.setBizModel(model);

            AlipayTradeRefundResponse alipay_response = client.execute(alipay_request);
            log.info("refund info, {}", alipay_response);
            if(alipay_response.isSuccess()) {
                result.setRefundFee(alipay_response.getRefundFee());
                return result;
            }
        }catch (Exception e) {}
        throw new XmallException(ResultCode.PAY_ALIPAY_REFUND_ERROR);
    }
}
